<?php
declare (strict_types = 1);

namespace app\admin\controller;

use think\exception\HttpResponseException;
use app\BaseController;
use think\facade\Cache;
use app\admin\model\auth\AdminModel;
use think\facade\Log;

class Base extends BaseController
{
    private const SPECIAL_PERMISSIONS = [
        'common:upload:list' => ['common:upload:upload']
        // 'module:list' => ['module:view', 'module:export'],可继续映射其他权限
    ];
    //定义固定权限标识（配合前端）
    private const FIXED_PERMISSIONS = [
        'auth:admin:userinfo',
        'auth:menu:list'
    ];
    public function initialize()
    {
        $userInfo = $this->validateToken();
        if (!$userInfo) {
            $this->unauthorized('凭证过期，请重新登录');
        }
        
        $this->refreshUserPermissions($userInfo['id']);
        
        if (!$this->checkPermission($userInfo)) {
            $this->forbidden('无操作权限，请联系管理员');
        }
    }

    protected function validateToken(): ?array
    {
        $token = getHeaderToken();
        return getJWT($token) ?: null;
    }
    
    protected function refreshUserPermissions(int $userId): void
    {
        $permissionKey = 'user_permission_' . $userId;
        $permissions = Cache::get($permissionKey);
        
        if (is_array($permissions) && !empty($permissions)) {
            return;
        }
        
        try {
            $adminModel = new AdminModel();
            $admin = $adminModel::find($userId);
            
            if ($admin && method_exists($admin, 'getAllPermissions')) {
                $permissions = $admin->getAllPermissions($userId);
            } else {
                $permissions = [];
            }
            $permissions = $this->addSpecialPermissions($permissions);
            $permissions = $this->addFixedPermissions($permissions, $userId);
            Cache::set($permissionKey, $permissions, 7200);
            
        } catch (\Throwable $e) {
            Log::error("刷新用户 {$userId} 权限缓存失败：" . $e->getMessage());
            Cache::set($permissionKey, [], 300); // 5分钟短缓存
        }
    }

    protected function addSpecialPermissions(array $permissions): array
    {
        foreach (self::SPECIAL_PERMISSIONS as $sourcePermission => $additionalPermissions) {
            if (in_array($sourcePermission, $permissions)) {
                foreach ($additionalPermissions as $additionalPermission) {
                    if (!in_array($additionalPermission, $permissions)) {
                        $permissions[] = $additionalPermission;
                    }
                }
            }
        }
        return array_unique($permissions); 
    }
    protected function addFixedPermissions(array $permissions, int $userId): array
    {
        if ($userId > 0) {
            foreach (self::FIXED_PERMISSIONS as $fixedPermission) {
                if (!in_array($fixedPermission, $permissions)) {
                    $permissions[] = $fixedPermission;
                }
            }
        }
        return array_unique($permissions);
    }
    
    protected function checkPermission(array $userInfo): bool
    {
        if ($userInfo['id'] == 1) {
            return true;
        }
        
        $currentRoute = $this->getCurrentRoute();
        $permissionKey = 'user_permission_' . $userInfo['id'];
        $permissions = Cache::get($permissionKey, []);
        
        return in_array($currentRoute, $permissions);
    }
    
    protected function getCurrentRoute(): string
    {
        $route = strtolower(request()->controller() . '/' . request()->action());
        return str_replace(['/', '.'], ':', $route);
    }
    
    protected function unauthorized(string $message = 'Unauthorized'): void
    {
        throw new HttpResponseException(json([
            'code' => 401,
            'msg'  => $message,
            'data' => [],
        ]));
    }
    
    protected function forbidden(string $message = 'Forbidden'): void
    {
        throw new HttpResponseException(json([
            'code' => 403,
            'msg'  => $message,
            'data' => [],
        ]));
    }
}